package com.xinggq.auth.service.config;

import com.xinggq.auth.api.exception.AuthException;
import feign.Logger;
import feign.RequestInterceptor;
import feign.codec.ErrorDecoder;
import feign.codec.ErrorDecoder.Default;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;

/**
 * Feign配置类
 * 启用Feign客户端，用于服务间调用
 * 职责：
 * 1. 启用Feign客户端并指定扫描包路径
 * 2. 配置Feign客户端日志级别
 * 3. 添加请求拦截器，用于传递认证信息
 * 4. 自定义错误解码器，优化异常处理
 *
 * @author xinggq
 * @since 2024-01-01
 */
@Configuration
@EnableFeignClients(basePackages = "com.xinggq.auth.service.feign")
@Slf4j
public class FeignConfig {

    /**
     * 配置Feign客户端日志级别
     * NONE: 不记录日志
     * BASIC: 仅记录请求方法、URL、响应状态码及执行时间
     * HEADERS: 记录BASIC级别的基础上，记录请求和响应的header
     * FULL: 记录请求和响应的header、body和元数据
     */
    @Bean
    public Logger.Level feignLoggerLevel() {
        return Logger.Level.BASIC;
    }

    /**
     * 请求拦截器
     * 用于在请求发送前添加认证信息等header
     */
    @Bean
    public RequestInterceptor requestInterceptor() {
        return requestTemplate -> {
            // 可以在这里添加认证信息、租户ID等通用header
            //requestTemplate.header(HttpHeaders.ACCEPT, "application/json");
            //requestTemplate.header(HttpHeaders.CONTENT_TYPE, "application/json");
            
            // 如果需要传递当前请求的认证信息，可以从SecurityContext获取并添加
            // 例如：requestTemplate.header(HttpHeaders.AUTHORIZATION, "Bearer " + getCurrentToken());
        };
    }

    /**
     * 自定义错误解码器
     * 用于将Feign调用异常转换为业务异常
     * 所有非成功的响应都会被解码为对应的业务异常
     */
    @Bean
    public ErrorDecoder errorDecoder() {
        return (methodKey, response) -> {
            // 只有状态码为200 OK的响应被视为成功
            if (response.status() == HttpStatus.OK.value()) {
                return new Default().decode(methodKey, response);
            }

            log.error("HTTP请求失败, url:{},状态码: {}, 响应: {}",response.request().url(), response.status(), response.body());
            // 根据响应状态码和内容，转换为对应的业务异常
            if (HttpStatus.valueOf(response.status()).is4xxClientError()) {
                return AuthException.serviceCallFailed("调用服务失败，请检查请求参数");
            } else if (HttpStatus.valueOf(response.status()).is5xxServerError()) {
                return AuthException.serviceCallFailed("服务暂时不可用，请稍后重试");
            } else {
                // 处理其他非成功状态码
                return AuthException.serviceCallFailed("服务调用异常，状态码: " + response.status());
            }
        };
    }
}